package com.icongyou.enterprise.talent_profile.controller;

import com.icongyou.enterprise.common.result.Result;
import com.icongyou.enterprise.data_aggregation.entity.vo.StudentTopSubmissionDetailVO;
import com.icongyou.enterprise.data_aggregation.entity.vo.StudentTopSubmissionSimpleVO;
import com.icongyou.enterprise.talent_profile.entity.vo.*;
import com.icongyou.enterprise.talent_profile.service.ProfileService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

/**
 * ProfileController 测试类
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("学生档案Controller测试")
class ProfileControllerTest {

    @Mock
    private ProfileService profileService;

    @InjectMocks
    private ProfileController profileController;

    private static final String STUDENT_ID = "660e8400-e29b-41d4-a716-446655440105";
    private static final String COURSE_ID = "course-001";
    private static final String SUBMISSION_ID = "submission-001";

    // ==================== getStudentBasicInfo 测试 ====================

    @Test
    @DisplayName("获取学生基础信息 - 成功")
    void testGetStudentBasicInfo_Success() {
        // Arrange
        StudentBasicVO basicVO = createStudentBasicVO();
        when(profileService.getStudentBasicInfo(STUDENT_ID)).thenReturn(basicVO);

        // Act
        Result<StudentBasicVO> result = profileController.getStudentBasicInfo(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(basicVO, result.getData());
        assertEquals("张三", result.getData().getRealName());
        verify(profileService).getStudentBasicInfo(STUDENT_ID);
    }

    @Test
    @DisplayName("获取学生基础信息 - 服务层异常")
    void testGetStudentBasicInfo_ServiceException() {
        // Arrange
        when(profileService.getStudentBasicInfo(STUDENT_ID))
            .thenThrow(new RuntimeException("数据库连接失败"));

        // Act
        Result<StudentBasicVO> result = profileController.getStudentBasicInfo(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(500, result.getCode());
        assertEquals("获取学生信息失败", result.getMessage());
        assertNull(result.getData());
    }

    @Test
    @DisplayName("获取学生基础信息 - 空数据")
    void testGetStudentBasicInfo_NullData() {
        // Arrange
        when(profileService.getStudentBasicInfo(STUDENT_ID)).thenReturn(null);

        // Act
        Result<StudentBasicVO> result = profileController.getStudentBasicInfo(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertNull(result.getData());
    }

    // ==================== getLearningOverview 测试 ====================

    @Test
    @DisplayName("获取学习概览 - 成功")
    void testGetLearningOverview_Success() {
        // Arrange
        LearningOverviewRespVO overview = createLearningOverview();
        when(profileService.getLearningOverview(STUDENT_ID, 1, 10)).thenReturn(overview);

        // Act
        Result<LearningOverviewRespVO> result = profileController.getLearningOverview(STUDENT_ID, 1, 10);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(overview, result.getData());
        assertEquals("张三", result.getData().getRealName());
        verify(profileService).getLearningOverview(STUDENT_ID, 1, 10);
    }

    @Test
    @DisplayName("获取学习概览 - 默认分页参数")
    void testGetLearningOverview_DefaultPagination() {
        // Arrange
        LearningOverviewRespVO overview = createLearningOverview();
        when(profileService.getLearningOverview(STUDENT_ID, 1, 10)).thenReturn(overview);

        // Act
        Result<LearningOverviewRespVO> result = profileController.getLearningOverview(STUDENT_ID, 1, 10);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        verify(profileService).getLearningOverview(STUDENT_ID, 1, 10);
    }

    @Test
    @DisplayName("获取学习概览 - 自定义分页参数")
    void testGetLearningOverview_CustomPagination() {
        // Arrange
        LearningOverviewRespVO overview = createLearningOverview();
        when(profileService.getLearningOverview(STUDENT_ID, 2, 20)).thenReturn(overview);

        // Act
        Result<LearningOverviewRespVO> result = profileController.getLearningOverview(STUDENT_ID, 2, 20);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        verify(profileService).getLearningOverview(STUDENT_ID, 2, 20);
    }

    @Test
    @DisplayName("获取学习概览 - 服务层异常")
    void testGetLearningOverview_ServiceException() {
        // Arrange
        when(profileService.getLearningOverview(STUDENT_ID, 1, 10))
            .thenThrow(new RuntimeException("查询失败"));

        // Act
        Result<LearningOverviewRespVO> result = profileController.getLearningOverview(STUDENT_ID, 1, 10);

        // Assert
        assertNotNull(result);
        assertEquals(500, result.getCode());
        assertEquals("获取学习概览失败", result.getMessage());
        assertNull(result.getData());
    }

    // ==================== getStudentCourses 测试 ====================

    @Test
    @DisplayName("获取学生课程列表 - 成功")
    void testGetStudentCourses_Success() {
        // Arrange
        List<StudentCourseVO> courses = createStudentCourses();
        when(profileService.getStudentCourses(STUDENT_ID)).thenReturn(courses);

        // Act
        Result<List<StudentCourseVO>> result = profileController.getStudentCourses(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(3, result.getData().size());
        assertEquals("Java编程基础", result.getData().get(0).getCourseName());
        verify(profileService).getStudentCourses(STUDENT_ID);
    }

    @Test
    @DisplayName("获取学生课程列表 - 空列表")
    void testGetStudentCourses_EmptyList() {
        // Arrange
        when(profileService.getStudentCourses(STUDENT_ID)).thenReturn(Collections.emptyList());

        // Act
        Result<List<StudentCourseVO>> result = profileController.getStudentCourses(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertTrue(result.getData().isEmpty());
    }

    @Test
    @DisplayName("获取学生课程列表 - 服务层异常")
    void testGetStudentCourses_ServiceException() {
        // Arrange
        when(profileService.getStudentCourses(STUDENT_ID))
            .thenThrow(new RuntimeException("数据库错误"));

        // Act
        Result<List<StudentCourseVO>> result = profileController.getStudentCourses(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(500, result.getCode());
        assertEquals("获取课程列表失败", result.getMessage());
        assertNull(result.getData());
    }

    // ==================== getTopSubmissionsSimple 测试 ====================

    @Test
    @DisplayName("获取核心成果简版 - 成功")
    void testGetTopSubmissionsSimple_Success() {
        // Arrange
        List<StudentTopSubmissionSimpleVO> submissions = createTopSubmissionsSimple();
        when(profileService.getStudentTopSubmissionsSimple(STUDENT_ID)).thenReturn(submissions);

        // Act
        Result<List<StudentTopSubmissionSimpleVO>> result = 
            profileController.getTopSubmissionsSimple(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(2, result.getData().size());
        verify(profileService).getStudentTopSubmissionsSimple(STUDENT_ID);
    }

    @Test
    @DisplayName("获取核心成果简版 - 空列表")
    void testGetTopSubmissionsSimple_EmptyList() {
        // Arrange
        when(profileService.getStudentTopSubmissionsSimple(STUDENT_ID))
            .thenReturn(Collections.emptyList());

        // Act
        Result<List<StudentTopSubmissionSimpleVO>> result = 
            profileController.getTopSubmissionsSimple(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertTrue(result.getData().isEmpty());
    }

    // ==================== getTopSubmissionsDetail 测试 ====================

    @Test
    @DisplayName("获取核心成果详情 - 成功")
    void testGetTopSubmissionsDetail_Success() {
        // Arrange
        List<StudentTopSubmissionDetailVO> submissions = createTopSubmissionsDetail();
        when(profileService.getStudentTopSubmissionsDetail(STUDENT_ID)).thenReturn(submissions);

        // Act
        Result<List<StudentTopSubmissionDetailVO>> result = 
            profileController.getTopSubmissionsDetail(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(2, result.getData().size());
        verify(profileService).getStudentTopSubmissionsDetail(STUDENT_ID);
    }

    @Test
    @DisplayName("获取核心成果详情 - 空列表")
    void testGetTopSubmissionsDetail_EmptyList() {
        // Arrange
        when(profileService.getStudentTopSubmissionsDetail(STUDENT_ID))
            .thenReturn(Collections.emptyList());

        // Act
        Result<List<StudentTopSubmissionDetailVO>> result = 
            profileController.getTopSubmissionsDetail(STUDENT_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertTrue(result.getData().isEmpty());
    }

    // ==================== getSubmissionDetail 测试 ====================

    @Test
    @DisplayName("获取提交详情 - 成功")
    void testGetSubmissionDetail_Success() {
        // Arrange
        SubmissionDetailVO detail = createSubmissionDetail();
        when(profileService.getSubmissionDetailById(SUBMISSION_ID)).thenReturn(detail);

        // Act
        Result<SubmissionDetailVO> result = profileController.getSubmissionDetail(SUBMISSION_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(detail, result.getData());
        assertEquals("在线商城系统", result.getData().getAssignmentName());
        verify(profileService).getSubmissionDetailById(SUBMISSION_ID);
    }

    @Test
    @DisplayName("获取提交详情 - 空数据")
    void testGetSubmissionDetail_NullData() {
        // Arrange
        when(profileService.getSubmissionDetailById(SUBMISSION_ID)).thenReturn(null);

        // Act
        Result<SubmissionDetailVO> result = profileController.getSubmissionDetail(SUBMISSION_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertNull(result.getData());
    }

    // ==================== getTopSubmissionByStudentAndCourse 测试 ====================

    @Test
    @DisplayName("获取课程最高分提交 - 成功")
    void testGetTopSubmissionByStudentAndCourse_Success() {
        // Arrange
        CourseTopSubmissionVO topSubmission = createCourseTopSubmission();
        when(profileService.getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID))
            .thenReturn(topSubmission);

        // Act
        Result<CourseTopSubmissionVO> result = 
            profileController.getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertEquals(topSubmission, result.getData());
        assertEquals(BigDecimal.valueOf(95.0), result.getData().getFinalScore());
        verify(profileService).getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID);
    }

    @Test
    @DisplayName("获取课程最高分提交 - 服务层异常")
    void testGetTopSubmissionByStudentAndCourse_ServiceException() {
        // Arrange
        when(profileService.getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID))
            .thenThrow(new RuntimeException("学生未选修该课程"));

        // Act
        Result<CourseTopSubmissionVO> result = 
            profileController.getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID);

        // Assert
        assertNotNull(result);
        assertEquals(500, result.getCode());
        assertEquals("学生未选修该课程", result.getMessage());
        assertNull(result.getData());
    }

    @Test
    @DisplayName("获取课程最高分提交 - 空数据")
    void testGetTopSubmissionByStudentAndCourse_NullData() {
        // Arrange
        when(profileService.getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID))
            .thenReturn(null);

        // Act
        Result<CourseTopSubmissionVO> result = 
            profileController.getTopSubmissionByStudentAndCourse(STUDENT_ID, COURSE_ID);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        assertNull(result.getData());
    }

    // ==================== 边界条件测试 ====================

    @Test
    @DisplayName("获取学习概览 - 分页参数为0")
    void testGetLearningOverview_ZeroPagination() {
        // Arrange
        LearningOverviewRespVO overview = createLearningOverview();
        when(profileService.getLearningOverview(STUDENT_ID, 0, 0)).thenReturn(overview);

        // Act
        Result<LearningOverviewRespVO> result = profileController.getLearningOverview(STUDENT_ID, 0, 0);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        verify(profileService).getLearningOverview(STUDENT_ID, 0, 0);
    }

    @Test
    @DisplayName("获取学习概览 - 大分页参数")
    void testGetLearningOverview_LargePagination() {
        // Arrange
        LearningOverviewRespVO overview = createLearningOverview();
        when(profileService.getLearningOverview(STUDENT_ID, 100, 1000)).thenReturn(overview);

        // Act
        Result<LearningOverviewRespVO> result = 
            profileController.getLearningOverview(STUDENT_ID, 100, 1000);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        verify(profileService).getLearningOverview(STUDENT_ID, 100, 1000);
    }

    @Test
    @DisplayName("获取学生基础信息 - 特殊字符学生ID")
    void testGetStudentBasicInfo_SpecialCharacterId() {
        // Arrange
        String specialId = "student@#$%";
        StudentBasicVO basicVO = createStudentBasicVO();
        when(profileService.getStudentBasicInfo(specialId)).thenReturn(basicVO);

        // Act
        Result<StudentBasicVO> result = profileController.getStudentBasicInfo(specialId);

        // Assert
        assertNotNull(result);
        assertEquals(200, result.getCode());
        verify(profileService).getStudentBasicInfo(specialId);
    }

    // ==================== Helper Methods ====================

    private StudentBasicVO createStudentBasicVO() {
        StudentBasicVO vo = new StudentBasicVO();
        vo.setStudentId(STUDENT_ID);
        vo.setRealName("张三");
        vo.setMajor("计算机科学与技术");
        vo.setEnrollmentYear(2021);
        vo.setEmail("zhangsan@example.com");
        vo.setPhone("13800138000");
        vo.setGender(1);
        vo.setSchoolName("XX大学");
        vo.setClassName("计科2101");
        return vo;
    }

    private LearningOverviewRespVO createLearningOverview() {
        LearningOverviewRespVO vo = new LearningOverviewRespVO();
        vo.setStudentId(STUDENT_ID);
        vo.setRealName("张三");
        
        // 设置课程性能列表
        List<CoursePerformanceSimpleVO> performances = new ArrayList<>();
        CoursePerformanceSimpleVO perf1 = new CoursePerformanceSimpleVO();
        perf1.setCourseId("course-1");
        perf1.setCourseName("Java编程");
        perf1.setTotalScore(88.0);
        perf1.setClassRanking(5);
        performances.add(perf1);
        vo.setCoursePerformance(performances);
        
        // 设置分页信息
        PaginationVO pagination = PaginationVO.builder()
            .page(1)
            .size(10)
            .total(5)
            .totalPages(1)
            .build();
        vo.setPagination(pagination);
        
        return vo;
    }

    private List<StudentCourseVO> createStudentCourses() {
        List<StudentCourseVO> courses = new ArrayList<>();
        
        StudentCourseVO course1 = new StudentCourseVO();
        course1.setCourseId("course-1");
        course1.setCourseName("Java编程基础");
        course1.setScore(BigDecimal.valueOf(88.5));
        course1.setCourseRank(5);
        course1.setAcademicYear("2023-2024");
        course1.setTeacherName("李老师");
        course1.setStudentCount(120);
        courses.add(course1);
        
        StudentCourseVO course2 = new StudentCourseVO();
        course2.setCourseId("course-2");
        course2.setCourseName("数据结构与算法");
        course2.setScore(BigDecimal.valueOf(82.0));
        course2.setCourseRank(15);
        course2.setAcademicYear("2023-2024");
        course2.setStudentCount(100);
        courses.add(course2);
        
        StudentCourseVO course3 = new StudentCourseVO();
        course3.setCourseId("course-3");
        course3.setCourseName("数据库系统");
        course3.setScore(BigDecimal.valueOf(90.0));
        course3.setCourseRank(3);
        course3.setAcademicYear("2023-2024");
        courses.add(course3);
        
        return courses;
    }

    private List<StudentTopSubmissionSimpleVO> createTopSubmissionsSimple() {
        List<StudentTopSubmissionSimpleVO> submissions = new ArrayList<>();
        
        StudentTopSubmissionSimpleVO sub1 = new StudentTopSubmissionSimpleVO();
        sub1.setSubmissionId("sub-1");
        sub1.setAssignmentName("在线商城系统");
        sub1.setFinalScore(95.0);
        sub1.setFullScore(100.0);
        sub1.setCourseName("Java Web开发");
        sub1.setSubmissionTime(LocalDateTime.now().minusDays(7));
        submissions.add(sub1);
        
        StudentTopSubmissionSimpleVO sub2 = new StudentTopSubmissionSimpleVO();
        sub2.setSubmissionId("sub-2");
        sub2.setAssignmentName("学生管理系统");
        sub2.setFinalScore(92.0);
        sub2.setFullScore(100.0);
        sub2.setCourseName("软件工程");
        sub2.setSubmissionTime(LocalDateTime.now().minusDays(14));
        submissions.add(sub2);
        
        return submissions;
    }

    private List<StudentTopSubmissionDetailVO> createTopSubmissionsDetail() {
        List<StudentTopSubmissionDetailVO> submissions = new ArrayList<>();
        
        StudentTopSubmissionDetailVO sub1 = new StudentTopSubmissionDetailVO();
        sub1.setSubmissionId("sub-1");
        sub1.setAssignmentName("在线商城系统");
        sub1.setFinalScore(95.0);
        sub1.setFullScore(100.0);
        sub1.setTextComment("设计合理，代码质量高");
        sub1.setCourseName("Java Web开发");
        sub1.setSubmissionTime(LocalDateTime.now().minusDays(7));
        submissions.add(sub1);
        
        StudentTopSubmissionDetailVO sub2 = new StudentTopSubmissionDetailVO();
        sub2.setSubmissionId("sub-2");
        sub2.setAssignmentName("学生管理系统");
        sub2.setFinalScore(92.0);
        sub2.setFullScore(100.0);
        sub2.setTextComment("功能完整，有创新");
        sub2.setCourseName("软件工程");
        sub2.setSubmissionTime(LocalDateTime.now().minusDays(14));
        submissions.add(sub2);
        
        return submissions;
    }

    private SubmissionDetailVO createSubmissionDetail() {
        SubmissionDetailVO vo = new SubmissionDetailVO();
        vo.setSubmissionId(SUBMISSION_ID);
        vo.setAssignmentName("在线商城系统");
        vo.setCourseName("Java Web开发");
        vo.setFinalScore(95.0);
        vo.setSubmissionTime(LocalDateTime.now().minusDays(7));
        vo.setTextComment("设计合理，代码质量高，功能完整");
        vo.setContentUrl("http://example.com/submissions/001");
        vo.setStatus("graded");
        vo.setFullScore(100.0);
        return vo;
    }

    private CourseTopSubmissionVO createCourseTopSubmission() {
        CourseTopSubmissionVO vo = new CourseTopSubmissionVO();
        vo.setSubmissionId("sub-top-1");
        vo.setAssignmentId("assignment-1");
        vo.setAssignmentName("期末大作业");
        vo.setFinalScore(BigDecimal.valueOf(95.0));
        vo.setFullScore(BigDecimal.valueOf(100.0));
        vo.setSubmissionTime(LocalDateTime.now().minusDays(10));
        vo.setTextComment("优秀作品");
        vo.setTeacherName("李老师");
        vo.setContentUrl("http://example.com/submissions/top-1");
        return vo;
    }
}
